// 线程池头文件

#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP

#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>
#include <atomic>
#include <optional>

/**
 * 线程池支持任务队列、线程管理、异常处理和优雅关闭等功能，
 * 适用于需要高效处理大量异步任务的场景。
 */
class ThreadPool {
public:
    /**
     * @brief 构造函数：创建指定数量线程的线程池
     *
     * @param threads 线程池中的线程数量
     * @param queueCapacity 任务队列的最大容量（默认无限制）
     */
    explicit ThreadPool(size_t threads, size_t queueCapacity = std::numeric_limits<size_t>::max());

    // 禁止拷贝构造和赋值，避免资源管理问题
    ThreadPool(const ThreadPool &) = delete;
    ThreadPool &operator=(const ThreadPool &) = delete;

    // 支持移动语义，允许线程池资源的所有权转移
    ThreadPool(ThreadPool &&) noexcept;
    ThreadPool &operator=(ThreadPool &&) noexcept;

    /**
     * @brief 向线程池添加任务模板定义
     *
     * @tparam F 任务函数类型
     * @tparam Args 任务参数类型
     * @param f 任务函数
     * @param args 任务参数
     * @return 返回一个future对象，可用于获取任务结果
     */
    template<class F, class... Args>
    auto enqueue(F &&f, Args&&... args) -> std::future<typename std::invoke_result<F, Args...>::type>;

    /**
     * @brief 正常关闭线程池
     *
     * 等待所有已加入队列的任务完成执行，但不再接受新任务
     */
    void shutdown();

    /**
     * @brief 立即关闭线程池
     *
     * 停止接受新任务，并放弃队列中尚未开始执行的任务，
     * 但会等待当前正在执行的任务完成
     */
    void shutdownNow();

    /**
     * @brief 获取当前活跃的线程数量
     *
     * @return 正在执行任务的线程数量
     */
    size_t activeThreads() const;

    /**
     * @brief 获取当前等待执行的任务数量
     *
     * @return 任务队列中的任务数量
     */
    size_t waitingTasks() const;

    /**
     * @brief 检查线程池是否正在运行
     *
     * @return true 线程池正在运行中
     * @return false 线程池已停止
     */
    bool isRunning() const;

    /**
     * @brief 析构函数
     *
     * 确保线程池在销毁前被正确关闭
     */
    ~ThreadPool();

private:
    // 工作线程集合
    std::vector<std::thread> workers;

    // 任务队列（使用function<void()>存储通用任务）
    std::queue<std::function<void()>> tasks;

    // 同步原语
    mutable std::mutex queue_mutex;         // 保护任务队列的互斥锁
    std::condition_variable condition;      // 任务可用的条件变量

    // 线程池状态
    std::atomic<size_t> activeCount{ 0 };   // 当前活跃线程数
    std::atomic<bool> stop{ false };        // 正常关闭标志
    std::atomic<bool> terminate{ false };   // 强制终止标志
    const size_t queueCapacity;             // 任务队列最大容量
};

/**
 * @brief 向线程池添加任务的实现
 *
 * @tparam F 任务函数类型
 * @tparam Args 任务参数类型
 * @param f 任务函数
 * @param args 任务参数
 * @return 返回一个future对象，可用于获取任务结果
 */
template<class F, class... Args>
auto ThreadPool::enqueue(F &&f, Args&&... args)
-> std::future<typename std::invoke_result<F, Args...>::type> {
    using return_type = typename std::invoke_result<F, Args...>::type;

    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        // 等待队列空间
        if (queueCapacity != std::numeric_limits<size_t>::max()) {
            condition.wait(lock, [this] {
                return tasks.size() < queueCapacity || stop || terminate;
                });
        }
        if (stop || terminate)
            throw std::runtime_error("enqueue on stopped ThreadPool");
        tasks.emplace([task]() { (*task)(); });
    }
    // 通知等待的线程有新任务
    condition.notify_one();
    return res;
}

#endif // !THREADPOOL_HPP